﻿using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace MyWeb.ServiceBus.Gateway.Middleware
{
    public class HttpContextMiddleware
    {
        private readonly RequestDelegate _next;
        /// <summary>
        /// 计时器
        /// </summary>
        private Stopwatch? _stopwatch;
        private LoadBalance? balance;
        /// <summary>
        /// 构造 Http 请求中间件
        /// </summary>
        /// <param name="next"></param>
        /// <param name="loggerFactory"></param>
        /// <param name="cacheService"></param>
        public HttpContextMiddleware(RequestDelegate next) => _next = next;

        public async Task InvokeAsync(HttpContext context)
        {

            var path = context.Request.Path.ToUriComponent();
            // 获取原始请求的查询参数
            var queryString = context.Request.QueryString.ToUriComponent();
            if (path.IndexOf("/system/") == 0)
            {
                // 构建目标地址
                var requestUrl = $"https://localhost:7234/api/{path["/system/".Length..]}{queryString}";
                //this.SetRedirect(context, new Uri(requestUrl));
                this.SetLocation(context, new Uri(requestUrl));
                //await SendHttpClientAsync(context, new Uri(requestUrl));
                return;
            }
            if (path.IndexOf("/quartz/") == 0)
            {
                var requestUrl = $"https://localhost:9235{path.Replace("/quartz/", "/api/")}{queryString}";
                this.SetRedirect(context, new Uri(requestUrl));
                return;
            }
            if (path.IndexOf("/ecsb/") == 0)
            {
                var requestUrl = $"http://localhost:8235/api/{path["/ecsb/".Length..]}{queryString}";
                await this.SendHttpClientAsync(context, new Uri(requestUrl));
                return;
            }
            // 继续传递请求给下一个中间件
            await _next(context);
        }

        /// <summary>
        /// 发送307临时重定向
        /// </summary>
        /// <param name="context"></param>
        /// <param name="uri"></param>
        private void SetLocation(HttpContext context, Uri uri)
        {
            // 设置允许跨域请求
            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
            // 设置允许使用凭证（credentials）的选项
            context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            context.Response.Headers.Add("Access-Control-Allow-Headers", "Authorization");

            // 发送 HTTP 307 临时重定向响应，并保留原始请求的方法、路径和请求体参数
            context.Response.StatusCode = StatusCodes.Status307TemporaryRedirect;
            context.Response.Headers["Location"] = uri.ToString();
        }
        /// <summary>
        /// 设置跨域重定向请求
        /// </summary>
        /// <param name="context"></param>
        /// <param name="uri"></param>
        private void SetRedirect(HttpContext context, Uri uri)
        {

            // 保存原始请求的头部信息
            var originalHeaders = context.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToString());

            // 设置允许跨域
            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
            // 重定向到 WeatherForecast11
            context.Response.Redirect(uri.ToString());

            //获取重定向后的请求
            var redirectContext = context.Features.Get<IHttpResponseFeature>();
            if (redirectContext != null)
            {
                var redirectRequest = context.RequestServices.GetRequiredService<IHttpContextFactory>().Create((IFeatureCollection)redirectContext);

                // 将原始请求的头部信息复制到重定向后的请求中
                foreach (var header in originalHeaders)
                {
                    redirectRequest.Request.Headers[header.Key] = header.Value;
                }
            }
        }
        /// <summary>
        /// Http请求转发
        /// </summary>
        /// <param name="context"></param>
        /// <param name="uri">转发uri</param>
        /// <returns></returns>
        private async Task SendHttpClientAsync(HttpContext context, Uri uri)
        {
            var request = context.Request;

            // 构建代理请求
            var proxyRequest = new HttpRequestMessage()
            {
                Method = new HttpMethod(request.Method),
                RequestUri = uri,
                //RequestUri = new(request.GetEncodedUrl())
            };

            if (request.Body == null
            || (!request.ContentLength.HasValue && StringValues.IsNullOrEmpty(request.Headers["Transfer-Encoding"])))
            {
                proxyRequest.Content = null;
            }
            else
            {
                proxyRequest.Content = request.ContentLength is 0 ? new ByteArrayContent(Array.Empty<byte>()) : new StreamContent(context.Request.Body);

                if (!string.IsNullOrEmpty(request.ContentType))
                {
                    proxyRequest.Content.Headers.TryAddWithoutValidation("Content-Type", new[] { request.ContentType });
                }

                // The performance might be improved by retrieving the matching headers from the request
                // instead of calling request.Headers.TryGetValue for each used content header
                var matchingHeaders = new string[] { "Content-Length", "Content-Language", "Content-Location", "Content-Range", "Content-MD5", "Content-Disposition", "Content-Encoding" }
                    .Where(header => request.Headers.ContainsKey(header));

                foreach (var key in matchingHeaders)
                {
                    if (!request.Headers.TryGetValue(key, out var value))
                    {
                        continue;
                    }
                    proxyRequest.Content.Headers.TryAddWithoutValidation(key, value.ToArray());
                }
            }


            // 将原始请求标头复制到代理请求
            HashSet<string> UnsupportedHeaders = new(StringComparer.OrdinalIgnoreCase) { "host", "transfer-encoding" };
            foreach (var header in request.Headers)
            {
                if (!UnsupportedHeaders.Contains(header.Key))
                {
                    proxyRequest.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
                }
            }

            await using var content = await proxyRequest.Content.ReadAsStreamAsync();
            await content.CopyToAsync(context.Response.Body, context.RequestAborted);

            //HttpClient httpClient = new HttpClient();
            //// 发送代理请求并获取响应
            //var response = await httpClient.SendAsync(proxyRequest);
            //// 将响应发送回客户端
            //context.Response.StatusCode = (int)response.StatusCode;
            //await response.Content.CopyToAsync(context.Response.Body);
        }
    }
}
